package com.paradogs.framework.core.msg;

import com.baidu.bjf.remoting.protobuf.FieldType;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
import com.baidu.bjf.remoting.protobuf.annotation.ProtobufClass;
import com.baomidou.mybatisplus.annotation.TableField;
import com.paradogs.framework.common.pojo.cg.CGPrepareLogin;
import com.paradogs.framework.common.pojo.gc.GCAllocGateway;
import com.paradogs.framework.core.utils.BeanUtils;
import com.paradogs.framework.core.utils.ProtoUtils;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Arrays;

/**
 * @author: yumi
 * @date: 2023/2/15  21:12
 * @Description: 基础消息类，通过约定类名实现反射自动调用，
 * this 在子类使用时会指向子类对象，从而实现子类不需要实现接口就能自动转换
 */
//@Slf4j 不能加，jprotobuf 会自动解析所有属性
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PRMsg {

    /**
     * 消息头
     */
    @TableField(exist = false)
    @Protobuf(fieldType = FieldType.OBJECT, order = 1)
    private MsgHeader msgHeader;

    /**
     * 消息数据
     */
    @Protobuf(fieldType = FieldType.OBJECT, order = 2)
    private Object msgData;

    public <T> PRMsg(T data) {
        this.msgHeader = new MsgHeader();
        this.msgData = data;
    }
    public <T> PRMsg(String route, T data) {
        this.msgHeader = new MsgHeader();
        this.msgHeader.setRoute(route);
        this.msgData = data;
    }

    /**
     * 序列化（编码)
     * @param out
     */
    public void serialization(ByteBuf out) {

        // 字节消息特殊处理
        if (this.msgData instanceof byte[]) {
            out.writeBytes((byte[]) this.msgData);
            return;
        }
        // 待优化：基本数据类型特殊处理

        // 写入消息体
        byte[] bytes = ProtoUtils.encode(this.msgData);

        out.writeBytes(bytes);

    }

    /**
     * 反序列化（解码）
     * @param in
     */
    public void deserialization(ByteBuf in, Class<?> clz) throws IOException {
        // 读取消息体 byte 数组
        byte[] bytes = new byte[in.readableBytes()];
        in.readBytes(bytes);
        this.deserialization(bytes, clz);
    }

    public void deserialization(byte[] bytes, Class<?> clz) {
        this.msgData = ProtoUtils.decode(bytes, clz);
    }

    public void setMsgHeader(MsgHeader msgHeader) {
        this.msgHeader = msgHeader;
    }
}
